package myicesscheduler.web;

import java.io.File;
import java.io.FilenameFilter;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class AdminBackupCompressController implements Controller
{
   private static final String filenamePrefix = "Backup";
   private static final int minSizeInByte = 1024 * 1024 * 1; // 1MB
   private final static Log logger = LogFactory.getLog( AdminBackupCompressController.class );

   public ModelAndView handleRequest( HttpServletRequest request, HttpServletResponse response )
         throws Exception
   {
      if( false == LoginController.isAdmin( request ) ) return LectureListController.redirect();

      removeOldBackupFiles();
      compress();

      return AdminMenuController.redirect_toAnchor( "CompressedFiles" );
   }

   private void removeOldBackupFiles()
   {
      logger.info( "remove old backup files." );
      final String[] oldBackupFilenames = getZipBackupFilenames();
      for( final String oldBackupFilename : oldBackupFilenames )
      {
         final String filename = MyFolderUtil.backupFolder
               .getAbsolutePathOfFile( oldBackupFilename );

         final File fh = new File( filename );
         if( !fh.exists() )
         {
            logger.warn( "file does not exist: " + filename );
            continue;
         }
         if( !fh.canWrite() )
         {
            logger.warn( "no writing permission: " + filename );
            continue;
         }

         final boolean bDeleted = fh.delete();
         if( bDeleted )
            logger.info( "File successfully deleted: " + filename );
         else logger.warn( "Fail to delete file:" + filename );
      }
   }

   public static String[] compress()
   {
      final String prefixZipFilename = getBackupFilenameWithDate();
      final String zipFilenameForUpload = prefixZipFilename + ".upload";
      final String zipFilenameForDatabase = prefixZipFilename + ".database";

      final String parentOfUploadFolder = new File( MyFolderUtil.uploadFolder.getAbsolutePath() )
            .getParent();
      final String parentOfDatabaseFolder = new File( MyFolderUtil.databaseFolder.getAbsolutePath() )
            .getParent();

      final List< String > uploadFiles = Arrays.asList( MyFolderUtil.uploadFolder
            .getAbsolutePathOfFiles() );
      final List< String > databaseFiles = Arrays.asList( MyFolderUtil.databaseFolder
            .getAbsolutePathOfFiles() );

      final String[] zipFilesForUpload = MyFileCompressor.compressFiles( zipFilenameForUpload,
            parentOfUploadFolder, uploadFiles.toArray( new String[ uploadFiles.size() ] ),
            minSizeInByte,
            MyFileCompressor.CompressedFilenamePostfixType.THREE_DIGIT_START_FROM_ZERO );

      final String[] zipFilesForDatabase = MyFileCompressor.compressFiles( zipFilenameForDatabase,
            parentOfDatabaseFolder, databaseFiles.toArray( new String[ databaseFiles.size() ] ),
            minSizeInByte,
            MyFileCompressor.CompressedFilenamePostfixType.THREE_DIGIT_START_FROM_ZERO );

      final List< String > zipFiles = new LinkedList< String >();
      zipFiles.addAll( Arrays.asList( zipFilesForUpload ) );
      zipFiles.addAll( Arrays.asList( zipFilesForDatabase ) );
      return zipFiles.toArray( new String[ zipFiles.size() ] );
   }

   private static String getBackupFilenameWithoutDate()
   {
      final String zipFullPath = MyFolderUtil.backupFolder.getAbsolutePathOfFile( filenamePrefix );
      return zipFullPath;
   }

   private static String getBackupFilenameWithDate()
   {
      final Calendar calendar = Calendar.getInstance();
      final Date compressionDate = calendar.getTime();
      final Format formater = new SimpleDateFormat( "yyyy_MM_dd.HH_mm_ss" );
      final String datePostfix = formater.format( compressionDate );

      final String zipFullPath = getBackupFilenameWithoutDate() + "." + datePostfix;
      logger.info( "backup filename: " + zipFullPath );
      return zipFullPath;
   }

   static class ZipBackupFilenameFilter implements FilenameFilter
   {
      public boolean accept( File dir, String filename )
      {
         final String lowerCase = filename.toLowerCase();
         return lowerCase.startsWith( filenamePrefix.toLowerCase() + "." )
               && lowerCase.endsWith( ".zip" );
      }
   }

   public static String[] getZipBackupFilenames()
   {
      return new File( MyFolderUtil.backupFolder.getAbsolutePath() )
            .list( new ZipBackupFilenameFilter() );
   }
}
